package com.csap.framework.oauth2.security.servlet;

import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.util.SaTokenConsts;
import com.alibaba.fastjson.JSON;
import com.csap.framework.extension.result.ResultParam;
import com.csap.framework.extension.result.ResultUtil;
import com.csap.framework.oauth2.FindUserService;
import com.csap.framework.oauth2.client.Oauth2ClientProperties;
import com.csap.framework.oauth2.exception.Oauth2Exception;
import com.csap.framework.oauth2.security.Oauth2SecurityProperties;
import com.csap.framework.oauth2.security.SecurityFilter;
import com.csap.framework.oauth2.security.user.UserContext;
import com.csap.framework.util.CollectionsUtil;
import lombok.SneakyThrows;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * Servlet全局过滤器
 *
 * @author kong
 */
@Order(SaTokenConsts.ASSEMBLY_ORDER)
@Accessors(chain = true)
@Slf4j
public class SecurityServletFilter extends SecurityFilter<SecurityServletFilter> implements Filter {

    public SecurityServletFilter(SaOAuth2Config saOAuth2Config, FindUserService findUserService, Oauth2SecurityProperties oauth2SecurityProperties, Oauth2ClientProperties oauth2ClientProperties) {
        super(saOAuth2Config, findUserService, oauth2SecurityProperties, oauth2ClientProperties);
    }

    @SneakyThrows
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        try {
            doOptions((HttpServletResponse) response);
            // 执行全局过滤器
            filterMapping(((HttpServletRequest) request).getMethod());
            // 执行
            chain.doFilter(request, response);
        } catch (Throwable e) {
            log.error(e.getMessage(), e);
            HttpServletResponse response1 = (HttpServletResponse) response;
            ResultParam<?> resultParam = ResultUtil.serviceError();
            if (e instanceof SaTokenException) {
                response1.setStatus(((SaTokenException) e).getHttpStatus().value());
                resultParam = ResultUtil.error(((SaTokenException) e).getHttpStatus().value() + "", e.getMessage(), ((SaTokenException) e).getHttpStatus().getReasonPhrase());
            }
            if (e instanceof Oauth2Exception) {
                resultParam = ResultUtil.error(((Oauth2Exception) e).exceptionType().getHttpStatus().value() + "", e.getMessage(), ((Oauth2Exception) e).exceptionType().getHttpStatus().getReasonPhrase());
            }
            if (response.getContentType() == null) {
                response.setContentType("text/plain; charset=utf-8");
            }
            PrintWriter printWriter = response1.getWriter();
            printWriter.write(JSON.toJSONString(resultParam));
            printWriter.flush();
            printWriter.close();
        } finally {
            // 清除上下文
            UserContext.remove();
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }

    /**
     * 处理全局想要的头部信息
     *
     * @param response
     */
    protected void doOptions(HttpServletResponse response) {
        if (CollectionsUtil.isNotEmpty(oauth2SecurityProperties.getHeaders())) {
            oauth2SecurityProperties.getHeaders().forEach(response::addHeader);
        }
    }

}
